<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>游戏协议测试客户端</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <!-- 添加 protobufjs 库 -->
    <script src="https://cdn.jsdelivr.net/npm/protobufjs@7.2.5/dist/protobuf.min.js"></script>
    <style>
        body { font-family: 'Inter', sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; background-color: #111827; color: #d1d5db; overflow: hidden; }
        ::-webkit-scrollbar { width: 8px; }
        ::-webkit-scrollbar-track { background: #1f2937; }
        ::-webkit-scrollbar-thumb { background: #4b5563; border-radius: 4px; }
        ::-webkit-scrollbar-thumb:hover { background: #6b7280; }
        .main-tab.active { background-color: #374151; color: #ffffff; border-left-color: #3b82f6; }
        .protocol-tab.active { background-color: #3b82f6; color: #ffffff; }
        .btn-disabled { background-color: #4b5563; cursor: not-allowed; }
    </style>
</head>
<body class="">
    <div class="flex h-screen w-screen">
        <!-- Tier 1: 最左侧的主功能 Tab -->
        <div class="w-48 bg-gray-900 border-r border-gray-700 flex-shrink-0 select-none">
            <nav class="p-2 mt-4">
                <ul>
                    <li><a href="#" id="main-tab-1" class="main-tab active flex items-center px-4 py-3 text-gray-300 rounded-md transition-colors duration-200 hover:bg-gray-700 hover:text-white border-l-4 border-blue-500"><svg class="w-6 h-6 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"></path></svg><span>协议测试</span></a></li>
                </ul>
            </nav>
        </div>

        <!-- 协议测试主内容区 -->
        <div id="main-content-1" class="flex flex-1">
            <!-- Tier 2: 连接控制 -->
            <div class="w-80 bg-gray-800 p-4 border-r border-gray-700 flex flex-col select-none">
                <h2 class="text-lg font-semibold text-white mb-4">连接设置</h2>
                <div class="mb-4">
                    <label for="server-address" class="block text-sm font-medium text-gray-400 mb-2">服务器地址</label>
                    <input type="text" id="server-address" class="w-full bg-gray-700 border border-gray-600 text-white rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder="例如: ws://127.0.0.1:8080 或 tcp://127.0.0.1:9090">
                </div>
                <button id="connect-btn" class="w-full bg-blue-600 text-white font-bold py-2 px-4 rounded-md hover:bg-blue-700 transition-colors duration-200 mb-4">连 接</button>
                
                <!-- 编解码脚本加载 -->
                <button id="load-codec-btn" class="w-full bg-purple-600 text-white font-bold py-2 px-4 rounded-md hover:bg-purple-700 transition-colors duration-200 mb-2">加载编解码脚本</button>
                <p id="codec-file-info" class="text-xs text-gray-500 mb-4 text-center">当前未使用自定义编解码</p>
                
                <!-- 业务脚本加载 -->
                <button id="load-business-script-btn" class="w-full bg-indigo-600 text-white font-bold py-2 px-4 rounded-md hover:bg-indigo-700 transition-colors duration-200 mb-2">加载业务脚本</button>
                <p id="business-script-status" class="text-xs text-gray-400 mb-4 text-center">当前未加载任何脚本</p>
                
                <div id="connection-status" class="mt-4 text-center text-sm text-gray-400">状态: 未连接</div>
                <div class="mt-auto border-t border-gray-700 pt-4">
                     <h3 class="text-md font-semibold text-white mb-2">日志输出</h3>
                     <div id="log-output" class="h-48 bg-gray-900 rounded-md p-2 text-xs text-gray-300 font-mono overflow-y-auto select-text cursor-text">欢迎使用协议测试工具...<br></div>
                </div>
            </div>

            <!-- Tier 3: 序列化方式与数据交互 -->
            <div class="flex-1 bg-gray-800 flex flex-col">
                <div class="flex-shrink-0 bg-gray-900 p-1"><nav class="flex space-x-1"><button id="proto-tab-protobuf" class="protocol-tab active px-4 py-2 text-sm font-medium rounded-md">Protobuf</button><button id="proto-tab-custom" class="protocol-tab px-4 py-2 text-sm font-medium rounded-md">自定义协议</button></nav></div>
                <div class="flex-1 p-4 overflow-y-auto">
                    <div id="proto-content-protobuf">
                        <h3 class="text-lg font-semibold text-white mb-4">使用 Protobuf 发送</h3>
                        <div class="mb-4 p-4 border border-dashed border-gray-600 rounded-md">
                            <button id="load-proto-dir-btn" class="w-full bg-indigo-600 text-white font-bold py-2 px-4 rounded-md hover:bg-indigo-700 transition-colors duration-200">选择 Proto 目录</button>
                            <p id="proto-dir-info" class="text-xs text-gray-500 mt-2">请先选择包含 .proto 文件的目录。</p>
                        </div>
                        <div class="grid grid-cols-2 gap-4">
                            <div>
                                <label for="proto-file-select" class="block text-sm font-medium text-gray-400 mb-2">Proto 文件</label>
                                <select id="proto-file-select" class="w-full bg-gray-700 border border-gray-600 text-white rounded-md px-3 py-2 mb-2"></select>
                                
                                <label for="proto-message-type" class="block text-sm font-medium text-gray-400 mb-2">消息类型</label>
                                <select id="proto-message-type" class="w-full bg-gray-700 border border-gray-600 text-white rounded-md px-3 py-2 mb-2"></select>
                                
                                <label for="proto-protocol-id" class="block text-sm font-medium text-gray-400 mb-2">协议号</label>
                                <input type="number" id="proto-protocol-id" class="w-full bg-gray-700 border border-gray-600 text-white rounded-md px-3 py-2 mb-2" placeholder="例如: 1001" value="1001">

                                <div id="proto-message-form" class="space-y-3 mt-4"></div>

                                <button id="send-protobuf-btn" class="mt-4 w-full bg-green-600 text-white font-bold py-2 px-4 rounded-md btn-disabled" disabled>发 送</button>
                            </div>
                            <div>
                                <label for="proto-receive-message-type" class="block text-sm font-medium text-gray-400 mb-2">接收消息类型</label>
                                <select id="proto-receive-message-type" class="w-full bg-gray-700 border border-gray-600 text-white rounded-md px-3 py-2 mb-2"></select>

                                <label for="proto-receive-protocol-id" class="block text-sm font-medium text-gray-400 mb-2">接收协议号 (用于匹配)</label>
                                <input type="text" id="proto-receive-protocol-id" class="w-full bg-gray-700 border border-gray-600 text-white rounded-md px-3 py-2 mb-2" placeholder="留空则匹配所有协议号">

                                <label for="protobuf-data-receive" class="block text-sm font-medium text-gray-400 mb-2">已接收数据 (解码后)</label>
                                <textarea id="protobuf-data-receive" rows="12" readonly class="w-full bg-gray-900 border border-gray-600 text-gray-300 rounded-md px-3 py-2 font-mono"></textarea>
                            </div>
                        </div>
                    </div>
                    <div id="proto-content-custom" class="hidden">
                        <h3 class="text-lg font-semibold text-white mb-4">发送自定义数据</h3>
                        <div class="grid grid-cols-2 gap-4">
                            <div>
                                <label for="custom-data-send" class="block text-sm font-medium text-gray-400 mb-2">待发送数据 (字符串)</label>
                                <textarea id="custom-data-send" rows="8" class="w-full bg-gray-700 border border-gray-600 text-white rounded-md px-3 py-2 font-mono" placeholder='{ "id": 1001, "action": "move" }'></textarea>
                                <button id="send-custom-btn" class="mt-2 w-full bg-green-600 text-white font-bold py-2 px-4 rounded-md btn-disabled" disabled>发 送</button>
                            </div>
                            <div>
                                <label for="custom-data-receive" class="block text-sm font-medium text-gray-400 mb-2">已接收数据</label>
                                <textarea id="custom-data-receive" rows="8" readonly class="w-full bg-gray-900 border border-gray-600 text-gray-300 rounded-md px-3 py-2 font-mono"></textarea>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <script>
        // --- 元素获取 ---
        const connectBtn = document.getElementById('connect-btn');
        const connectionStatus = document.getElementById('connection-status');
        const logOutput = document.getElementById('log-output');
        const sendCustomBtn = document.getElementById('send-custom-btn');
        const sendProtobufBtn = document.getElementById('send-protobuf-btn');
        const protoTabCustom = document.getElementById('proto-tab-custom');
        const protoTabProtobuf = document.getElementById('proto-tab-protobuf');
        const protoContentCustom = document.getElementById('proto-content-custom');
        const protoContentProtobuf = document.getElementById('proto-content-protobuf');
        const loadProtoDirBtn = document.getElementById('load-proto-dir-btn');
        const protoDirInfo = document.getElementById('proto-dir-info');
        const protoFileSelect = document.getElementById('proto-file-select');
        const protoMessageTypeSelect = document.getElementById('proto-message-type');
        const protoReceiveMessageTypeSelect = document.getElementById('proto-receive-message-type');
        const loadCodecBtn = document.getElementById('load-codec-btn');
        const codecFileInfo = document.getElementById('codec-file-info');
        
        // 业务脚本相关元素 - 简化
        const loadBusinessScriptBtn = document.getElementById('load-business-script-btn');
        const businessScriptStatus = document.getElementById('business-script-status');

        let isConnected = false;

        // --- 协议标签页切换 ---
        protoTabCustom.addEventListener('click', () => {
            protoTabCustom.classList.add('active');
            protoTabProtobuf.classList.remove('active');
            protoContentCustom.classList.remove('hidden');
            protoContentProtobuf.classList.add('hidden');
        });

        protoTabProtobuf.addEventListener('click', () => {
            protoTabProtobuf.classList.add('active');
            protoTabCustom.classList.remove('active');
            protoContentProtobuf.classList.remove('hidden');
            protoContentCustom.classList.add('hidden');
        });

        // --- 日志函数 ---
        function log(message, type = 'info') {
            const now = new Date().toLocaleTimeString();
            const colorMap = { info: 'text-gray-400', success: 'text-green-400', error: 'text-red-400', send: 'text-blue-400', receive: 'text-purple-400' };
            logOutput.innerHTML += `<span class="${colorMap[type] || 'text-gray-400'}">[${now}] ${message}</span><br>`;
            logOutput.scrollTop = logOutput.scrollHeight;
        }

        // --- 创建 Proto 表单字段的通用函数 ---
        async function createProtoFormFields(messageType, formContainerId) {
            const formContainer = document.getElementById(formContainerId);
            formContainer.innerHTML = ''; // 清空
            if (!messageType) return;
        
            const result = await window.api.getMessageDetails(messageType);
            if (result.success) {
                result.fields.forEach(field => {
                    const fieldId = `${formContainerId}-field-${field.name}`;
                    let labelText = `${field.name} (${field.type})`;
                    if (field.isRepeated) {
                        labelText += ' (repeated)';
                    }
                    let inputHtml = `<label for="${fieldId}" class="block text-sm font-medium text-gray-300">${labelText}</label>`;
                    
                    if (field.isMessageType) {
                        inputHtml += `<div id="${fieldId}" data-field-name="${field.name}" class="p-2 border border-gray-600 rounded-md mt-1 space-y-2 bg-gray-700"><span>嵌套对象，暂不支持直接编辑</span></div>`;
                    } else {
                        const placeholder = field.isRepeated ? '多个值请用英文逗号分隔' : '请输入值';
                        inputHtml += `<input type="text" id="${fieldId}" data-field-name="${field.name}" data-field-type="${field.type}" data-field-is-repeated="${field.isRepeated}" placeholder="${placeholder}" class="w-full bg-gray-600 border border-gray-500 text-white rounded-md px-2 py-1 mt-1">`;
                    }
        
                    formContainer.innerHTML += `<div>${inputHtml}</div>`;
                });
            } else {
                log(`获取消息详情失败: ${result.message}`, 'error');
            }
        }

        // --- 发送按钮状态更新 ---
        function updateSendButtonsState(enabled) {
            [sendCustomBtn, sendProtobufBtn].forEach(btn => {
                btn.disabled = !enabled;
                if (enabled) btn.classList.remove('btn-disabled');
                else btn.classList.add('btn-disabled');
            });
        }

        // --- 连接/断开逻辑 ---
        connectBtn.addEventListener('click', () => {
            if (isConnected) {
                window.api.disconnect();
            } else {
                const serverAddress = document.getElementById('server-address').value;
                if (!serverAddress) {
                    log('请输入服务器地址!', 'error');
                    return;
                }
                window.api.connect(serverAddress);
            }
        });

        // --- 本地存储功能 ---
        function saveLastPath(key, path) {
            localStorage.setItem(key, path);
        }
        
        function getLastPath(key) {
            return localStorage.getItem(key);
        }
        
        // --- 页面加载时恢复上次选择的路径 ---
        window.addEventListener('DOMContentLoaded', async () => {
            const lastProtoDir = getLastPath('lastProtoDir');
            const lastCodecScript = getLastPath('lastCodecScript');
            const lastBusinessScript = getLastPath('lastBusinessScript');
            
            // 恢复proto目录
            if (lastProtoDir) {
                protoDirInfo.textContent = `上次选择: ${lastProtoDir}`;
                protoDirInfo.classList.add('text-yellow-400');
                // 自动加载proto目录
                const result = await window.api.autoLoadProtoDir(lastProtoDir);
                if (result.success) {
                    protoDirInfo.textContent = `当前目录: ${result.path}`;
                    protoDirInfo.classList.remove('text-yellow-400');
                    protoDirInfo.classList.add('text-green-400');
                    
                    protoFileSelect.innerHTML = '<option value="">--请选择 proto 文件--</option>';
                    result.files.forEach(file => {
                        const option = document.createElement('option');
                        option.value = file;
                        option.textContent = file;
                        protoFileSelect.appendChild(option);
                    });
                    log(`自动加载 proto 目录: ${result.path}`, 'success');
                }
            }
            
            // 恢复编解码脚本
            if (lastCodecScript) {
                const fileName = lastCodecScript.split(/[\\\/]/).pop();
                codecFileInfo.textContent = `上次选择: ${fileName}`;
                codecFileInfo.classList.add('text-yellow-400');
                // 自动加载编解码脚本
                const result = await window.api.autoLoadCodecScript(lastCodecScript);
                if (result.success) {
                    codecFileInfo.textContent = `当前脚本: ${fileName}`;
                    codecFileInfo.classList.remove('text-yellow-400');
                    codecFileInfo.classList.add('text-green-400');
                    log(`自动加载编解码脚本: ${fileName}`, 'success');
                }
            }
            
            // 恢复业务脚本
            if (lastBusinessScript) {
                const fileName = lastBusinessScript.split(/[\\\/]/).pop();
                businessScriptStatus.textContent = `上次选择: ${fileName}`;
                businessScriptStatus.classList.add('text-yellow-400');
                // 自动加载业务脚本
                const result = await window.api.autoLoadBusinessScript(lastBusinessScript);
                if (result.success) {
                    businessScriptStatus.textContent = `已加载: ${result.fileName}`;
                    businessScriptStatus.classList.remove('text-yellow-400', 'text-gray-400');
                    businessScriptStatus.classList.add('text-green-400');
                    log(`自动加载业务脚本: ${result.fileName}`, 'success');
                }
            }
        });

        // --- 加载自定义编解码脚本 ---
        loadCodecBtn.addEventListener('click', async () => {
            const result = await window.api.loadCodecScript();
            if (result.success) {
                const fileName = result.filePath.split(/[\\\/]/).pop();
                codecFileInfo.textContent = `当前脚本: ${fileName}`;
                codecFileInfo.classList.remove('text-yellow-400');
                codecFileInfo.classList.add('text-green-400');
                log(`成功加载编解码脚本: ${fileName}`, 'success');
                // 保存路径
                saveLastPath('lastCodecScript', result.filePath);
            } else {
                log(result.message, 'error');
                codecFileInfo.textContent = '加载失败';
                codecFileInfo.classList.remove('text-green-400');
            }
        });

        // --- 业务脚本功能 - 修改为直接选择文件 ---
        loadBusinessScriptBtn.addEventListener('click', async () => {
            const result = await window.api.loadBusinessScriptFile();
            if (result.success) {
                businessScriptStatus.textContent = `已加载: ${result.fileName}`;
                businessScriptStatus.classList.remove('text-gray-400', 'text-yellow-400');
                businessScriptStatus.classList.add('text-green-400');
                log(`成功加载业务脚本: ${result.fileName}`, 'success');
                // 保存路径
                saveLastPath('lastBusinessScript', result.filePath);
            } else {
                businessScriptStatus.textContent = '加载失败';
                businessScriptStatus.classList.remove('text-green-400');
                businessScriptStatus.classList.add('text-red-400');
                log(`加载业务脚本失败: ${result.message}`, 'error');
            }
        });

        // --- 加载 Protobuf ---
        loadProtoDirBtn.addEventListener('click', async () => {
            const result = await window.api.loadProtoDir();
            if (result.success) {
                protoDirInfo.textContent = `当前目录: ${result.path}`;
                protoDirInfo.classList.remove('text-yellow-400');
                protoDirInfo.classList.add('text-green-400');
                log(`成功加载 proto 目录: ${result.path}`, 'success');
                // 保存路径
                saveLastPath('lastProtoDir', result.path);

                protoFileSelect.innerHTML = '<option value="">--请选择 proto 文件--</option>';
                result.files.forEach(file => {
                    const option = document.createElement('option');
                    option.value = file;
                    option.textContent = file;
                    protoFileSelect.appendChild(option);
                });
            } else {
                log(result.message, 'error');
                protoDirInfo.textContent = '加载失败';
                protoDirInfo.classList.remove('text-green-400');
            }
        });

        protoFileSelect.addEventListener('change', async (event) => {
            const selectedFile = event.target.value;
            protoMessageTypeSelect.innerHTML = '<option value="">--请先选择文件--</option>';
            protoReceiveMessageTypeSelect.innerHTML = '<option value="">--请先选择文件--</option>';
            document.getElementById('proto-message-form').innerHTML = ''; // 清空旧表单
            if (!selectedFile) return;

            const result = await window.api.loadProtoFile(selectedFile);
            if (result.success) {
                log(`解析 ${selectedFile} 成功`, 'success');
                protoMessageTypeSelect.innerHTML = '<option value="">--请选择消息类型--</option>';
                protoReceiveMessageTypeSelect.innerHTML = '<option value="">--请选择消息类型--</option>';
                result.types.forEach(type => {
                    const sendOption = document.createElement('option');
                    sendOption.value = type;
                    sendOption.textContent = type;
                    protoMessageTypeSelect.appendChild(sendOption);
                    
                    const receiveOption = document.createElement('option');
                    receiveOption.value = type;
                    receiveOption.textContent = type;
                    protoReceiveMessageTypeSelect.appendChild(receiveOption);
                });
            } else {
                log(`解析 ${selectedFile} 失败: ${result.message}`, 'error');
            }
        });

        // 在接收消息类型选择变化时通知主进程
        protoReceiveMessageTypeSelect.addEventListener('change', async (event) => {
            const receiveMessageType = event.target.value;
            if (receiveMessageType) {
                await window.api.setReceiveMessageType(receiveMessageType);
                log(`设置接收消息类型为: ${receiveMessageType}`, 'info');
            }
        });

        protoMessageTypeSelect.addEventListener('change', async (event) => {
            const messageType = event.target.value;
            // 同步接收区的下拉框
            protoReceiveMessageTypeSelect.value = messageType;
            // 同步设置接收消息类型
            if (messageType) {
                await window.api.setReceiveMessageType(messageType);
            }
            // 默认将协议号也同步过去
            const protocolIdInput = document.getElementById('proto-protocol-id');
            document.getElementById('proto-receive-protocol-id').value = protocolIdInput.value;

            createProtoFormFields(messageType, 'proto-message-form');
        });

        // --- 发送数据 ---
        sendCustomBtn.addEventListener('click', () => {
            const data = document.getElementById('custom-data-send').value;
            if (!data) {
                log('不能发送空数据', 'error');
                return;
            }
            window.api.sendData(data);
            log(`发送自定义数据: ${data}`, 'send');
        });

        sendProtobufBtn.addEventListener('click', async () => {
            const messageType = protoMessageTypeSelect.value;
            const protocolId = parseInt(document.getElementById('proto-protocol-id').value);
            
            if (!messageType) {
                log('请先选择消息类型', 'error');
                return;
            }
            
            if (isNaN(protocolId)) {
                log('请输入有效的协议号', 'error');
                return;
            }

            // 收集表单数据
            const formData = {};
            const formContainer = document.getElementById('proto-message-form');
            const inputs = formContainer.querySelectorAll('input[data-field-name]');
            
            inputs.forEach(input => {
                const fieldName = input.getAttribute('data-field-name');
                const fieldType = input.getAttribute('data-field-type');
                const isRepeated = input.getAttribute('data-field-is-repeated') === 'true';
                const value = input.value.trim();
                
                if (value) {
                    if (isRepeated) {
                        // 处理重复字段
                        const values = value.split(',').map(v => v.trim());
                        if (fieldType === 'int32' || fieldType === 'int64') {
                            formData[fieldName] = values.map(v => parseInt(v)).filter(v => !isNaN(v));
                        } else if (fieldType === 'float' || fieldType === 'double') {
                            formData[fieldName] = values.map(v => parseFloat(v)).filter(v => !isNaN(v));
                        } else {
                            formData[fieldName] = values;
                        }
                    } else {
                        // 处理单个字段
                        if (fieldType === 'int32' || fieldType === 'int64') {
                            const intValue = parseInt(value);
                            if (!isNaN(intValue)) formData[fieldName] = intValue;
                        } else if (fieldType === 'float' || fieldType === 'double') {
                            const floatValue = parseFloat(value);
                            if (!isNaN(floatValue)) formData[fieldName] = floatValue;
                        } else if (fieldType === 'bool') {
                            formData[fieldName] = value.toLowerCase() === 'true';
                        } else {
                            formData[fieldName] = value;
                        }
                    }
                }
            });

            const protobufData = {
                protocol: 'protobuf',
                messageType: messageType,
                protocolId: protocolId,
                payload: formData  // 改为 payload 而不是 data
            };

            window.api.sendData(JSON.stringify(protobufData));
            log(`发送 Protobuf 数据: ${messageType} (协议号: ${protocolId}) 序列化方式: ${protobufData.protocol}`, 'send');
        });

        // --- 事件监听 ---
        window.api.onConnectionStatus((data) => {
            const { status, message } = data;
            if (status === 'connected') {
                isConnected = true;
                connectBtn.textContent = '断开连接';
                connectBtn.classList.remove('bg-blue-600', 'hover:bg-blue-700');
                connectBtn.classList.add('bg-red-600', 'hover:bg-red-700');
                connectionStatus.textContent = `状态: ${message}`;
                connectionStatus.classList.remove('text-gray-400');
                connectionStatus.classList.add('text-green-400');
                updateSendButtonsState(true);
                log(`连接成功: ${message}`, 'success');
            } else if (status === 'disconnected') {
                isConnected = false;
                connectBtn.textContent = '连 接';
                connectBtn.classList.remove('bg-red-600', 'hover:bg-red-700');
                connectBtn.classList.add('bg-blue-600', 'hover:bg-blue-700');
                connectionStatus.textContent = '状态: 未连接';
                connectionStatus.classList.remove('text-green-400');
                connectionStatus.classList.add('text-gray-400');
                updateSendButtonsState(false);
                log('连接已断开', 'info');
            } else if (status === 'error') {
                isConnected = false;
                connectBtn.textContent = '连 接';
                connectBtn.classList.remove('bg-red-600', 'hover:bg-red-700');
                connectBtn.classList.add('bg-blue-600', 'hover:bg-blue-700');
                connectionStatus.textContent = '状态: 连接错误';
                connectionStatus.classList.remove('text-green-400');
                connectionStatus.classList.add('text-red-400');
                updateSendButtonsState(false);
                log(`连接错误: ${message}`, 'error');
            }
        });

        window.api.onLog((data) => {
            const { message, type } = data;
            log(message, type);
        });

        // 将 isMessageTypeMatch 函数提取到全局作用域
        function isMessageTypeMatch(actualType, expectedType) {
            if (!actualType || !expectedType) return true; // 如果任一为空，不进行匹配检查
            
            // 直接相等
            if (actualType === expectedType) return true;
            
            // 提取类型名（去掉命名空间前缀）
            const getTypeName = (type) => {
                const parts = type.split('.');
                return parts[parts.length - 1]; // 返回最后一部分
            };
            
            const actualTypeName = getTypeName(actualType);
            const expectedTypeName = getTypeName(expectedType);
            
            // 比较去掉命名空间后的类型名
            return actualTypeName === expectedTypeName;
        }

        window.api.onDataReceived((receivedData, protocol) => {
            console.log('onDataReceived 协议', protocol);
            if (protocol === 'protobuf-tcp' || protocol === 'ws-custom') {
                // 获取用户设置的接收协议号
                const currentReceiveProtocolId = document.getElementById('proto-receive-protocol-id').value;
                
                // 添加调试日志
                console.log('接收到数据:', receivedData);
                console.log('设置的过滤协议号:', currentReceiveProtocolId);
                
                // 检查是否需要过滤显示（只根据协议号过滤）
                let shouldDisplay = true;
                
                // 协议号过滤（如果用户填写了协议号）
                if (currentReceiveProtocolId && currentReceiveProtocolId.trim() !== '') {
                    const expectedProtocolId = parseInt(currentReceiveProtocolId.trim());
                    if (receivedData.protocolId !== expectedProtocolId) {
                        shouldDisplay = false;
                        console.log(`协议号不匹配，过滤数据: 接收到${receivedData.protocolId}, 期望${expectedProtocolId}`);
                    }
                }
                
                // 显示数据（去掉消息类型过滤）
                if (shouldDisplay) {
                    const formattedData = formatProtobufData(receivedData, '');
                    document.getElementById('protobuf-data-receive').value = formattedData;
                    log('接收到 Protobuf 数据', 'receive');
                    console.log('数据已显示在UI中');
                } else {
                    log(`过滤数据: 协议号=${receivedData.protocolId}`, 'info');
                }
            }
        });

        // --- 格式化 Protobuf 数据显示 ---
        function formatProtobufData(data, expectedMessageType) {
            console.log('formatProtobufData 输入:', data);
            
            function formatValue(value) {
                // 使用 protobuf.util.isLong 或 protobuf.util.Long.isLong
                if (protobuf.util.Long && protobuf.util.Long.isLong && protobuf.util.Long.isLong(value)) {
                    return value.toString();
                } else if (Array.isArray(value)) {
                    return value.map(formatValue);
                } else if (value && typeof value === 'object') {
                        const formatted = {};
                        for (const [key, val] of Object.entries(value)) {
                            formatted[key] = formatValue(val);
                        }
                        return formatted;
                    }
                    return value;
            }

            // 删除重复的 isMessageTypeMatch 函数定义
            // 删除消息类型匹配检查逻辑

            // 如果有data字段，只显示data部分
            if (data.data) {
                const result = {
                    protocolId: data.protocolId,
                    messageType: data.messageType,
                    fields: formatValue(data.data)
                };
                console.log('formatProtobufData 输出:', result);
                return JSON.stringify(result, null, 2);
            }

            // 否则显示完整数据
            const result = formatValue(data);
            console.log('formatProtobufData 输出 (完整):', result);
            return JSON.stringify(result, null, 2);
        }

    </script>
</body>
</html>
